﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;

namespace suirui.ZhuMu.Common
{
    public static class ExpressionAndSeesionMethod

    {
        public static Dictionary<string, object> _dictionary = new Dictionary<string, object>();

        public static TModel Trans<TModel, TModelDto>(TModelDto dto)
        {
            Type modelType = typeof(TModel);
            Type modelDtoType = typeof(TModelDto);

            //如果_dictionary中不存在该key，则存进去
            string key = $"{modelDtoType.Name}-->{modelType.Name}";
            if (!_dictionary.ContainsKey(key))
            {
                //创建一个lambda参数x，定义的对象为TModelDto
                ParameterExpression parameterExpression = Expression.Parameter(modelDtoType, "x");
                //开始生成lambda表达式
                List<MemberBinding> list = new List<MemberBinding>();
                foreach (var item in modelType.GetProperties())
                {
                    //为x参数表达式生成一个属性值
                    MemberExpression property = Expression.Property(parameterExpression, modelDtoType.GetProperty(item.Name));
                    //将该属性初始化 eg:No=x.No
                    MemberBinding memberBinding = Expression.Bind(item, property);
                    list.Add(memberBinding);
                }

                foreach (var item in typeof(TModel).GetFields())
                {
                    //为x参数表达式生成一个字段值
                    MemberExpression field = Expression.Field(parameterExpression, modelDtoType.GetField(item.Name));
                    //将该字段初始化
                    MemberBinding memberBinding = Expression.Bind(item, field);
                    list.Add(memberBinding);
                }
                //调用构造函数，初始化一个TModel eg: new{No=x.No...}
                MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(modelType), list);
                //创建lambda表达式  eg: x=>new{ No=x.No...}
                Expression<Func<TModelDto, TModel>> lambda = Expression.Lambda<Func<TModelDto, TModel>>(memberInitExpression, parameterExpression);
                //将lambda表达式生成委托
                Func<TModelDto, TModel> func = lambda.Compile();
                _dictionary[key] = func;
            }
            return ((Func<TModelDto, TModel>)_dictionary[key]).Invoke(dto);
        }
    }
}
